/*
 * ProgramacionLinealGeneral.java
 *
 * Created on 16 de marzo de 2002, 9:47
 */

package Utiles;

/**
 *
 * @author  spadilla
 * @version
 */
import drasys.or.mp.*;
import drasys.or.mp.lp.*;
import drasys.or.matrix.*;
import drasys.or.linear.algebra.*;
public abstract class ProgramacionLinealGeneral {
    
    private static  double[] vectorX;
    private static double Zoptimo;
    private static  double[] vectorXEcual;
    private static double ZoptimoEcual;
    private static  double[] vectorXMeta;
    private static double ZoptimoMeta;
    private static  double[] vectorXPCInf;
    
    public static void ProgramacionLineal(double[] matrizCoef) throws DuplicateException, NotFoundException,InvalidException,NoSolutionException, UnboundedException, InfeasibleException, ConvergenceException, ScaleException {
        
        SizableProblemI prob;
        LinearProgrammingI lp = new DenseSimplex();
        
        int n_variables=DatosEntrada.DatosContinuos.getNVariables();
        int n_restricciones=DatosEntrada.DatosContinuos.getNRestricciones();
        
        String[] variables=DatosEntrada.DatosContinuos.getSimboloVariable();
        String[] NameResticc=DatosEntrada.DatosContinuos.getRestriccionesName();
        int [] SignoRestricciones=DatosEntrada.DatosContinuos.getSimboloRestricciones();
        double[] ladoderecho=DatosEntrada.DatosContinuos.getLadosDerechos();
        double[][] coeficienteRestricc=DatosEntrada.DatosContinuos.getMatrizCoefRest();
        
        prob=new Problem(n_restricciones,n_variables);
        
        prob.getMetadata().put("lp.isMaximize", "true");
        
        for(int j=0;j<n_variables;j++){
            //asigna coef variables de la funcion objetivo
            prob.newVariable(variables[j]).setObjectiveCoefficient(matrizCoef[j]);
        }
        
        for(int k=0;k<n_restricciones;k++){
            byte signo=Constraint.FREE;
            
            if(SignoRestricciones[k]==(-1))
                signo= Constraint.LESS;
            if(SignoRestricciones[k]==(0))
                signo= Constraint.EQUAL;
            if(SignoRestricciones[k]==1)
                signo= Constraint.GREATER;
            
            prob.newConstraint(NameResticc[k]).setType(signo).setRightHandSide(ladoderecho[k]);
        }
        
        for(int j=0;j<n_variables;j++){
            for(int k=0;k<n_restricciones;k++){
                prob.setCoefficientAt(NameResticc[k],variables[j],coeficienteRestricc[k][j]);
                
            }
        }
        lp=new DenseSimplex(prob);
        double ans = lp.solve();
        //double ans = lp.getObjectiveValue();
        Zoptimo=ans;
        vectorX=lp.getSolution().getArray();
    }
    
    public static void ProgramacionMetas(String[] rest, String[] var, double[] VectCoef, int[]signos, double[] ladDer, double[][] matCoefRest) throws DuplicateException, NotFoundException,InvalidException,NoSolutionException, UnboundedException, InfeasibleException, ConvergenceException, ScaleException {
        
        SizableProblemI prob;
        LinearProgrammingI lp = new DenseSimplex();
        
        int n_variables=VectCoef.length;
        int n_restricciones=signos.length;
        String[] variables=var;
        String[] NameResticc=rest;
        int [] SignoRestricciones=signos;
        double[] ladoderecho=ladDer;
        double[][] coeficienteRestricc=matCoefRest;
        
        prob=new Problem(n_restricciones,n_variables);
        
        prob.getMetadata().put("lp.isMaximize", "true");
        
        for(int j=0;j<n_variables;j++){
            //asigna coef variables de la funcion objetivo
            prob.newVariable(variables[j]).setObjectiveCoefficient(VectCoef[j]);
        }
        
        for(int k=0;k<n_restricciones;k++){
            byte signo=Constraint.FREE;
            
            if(SignoRestricciones[k]==(-1))
                signo= Constraint.LESS;
            if(SignoRestricciones[k]==(0))
                signo= Constraint.EQUAL;
            if(SignoRestricciones[k]==1)
                signo= Constraint.GREATER;
            
            prob.newConstraint(NameResticc[k]).setType(signo).setRightHandSide(ladoderecho[k]);
        }
        
        for(int j=0;j<n_variables;j++){
            for(int k=0;k<n_restricciones;k++){
                prob.setCoefficientAt(NameResticc[k],variables[j],coeficienteRestricc[k][j]);
                
            }
        }
        lp=new DenseSimplex(prob);
        double ans = lp.solve();
        //double ans = lp.getObjectiveValue();
        ZoptimoMeta=ans;
        vectorXMeta=lp.getSolution().getArray();
        
        
    }
    
    public static void ProgramacionPCompromisoInfinito(double[]ladoDre,double[][]NewcoeficienteRestricc) throws DuplicateException, NotFoundException,InvalidException,NoSolutionException, UnboundedException, InfeasibleException, ConvergenceException, ScaleException {
        
        SizableProblemI prob;
        LinearProgrammingI lp = new DenseSimplex();
        
        int n_variables=DatosEntrada.DatosContinuos.getNVariables()+1;
        int n_funciones=DatosEntrada.DatosContinuos.getNFunciones();
        int n_restricciones=DatosEntrada.DatosContinuos.getNRestricciones()+n_funciones;
        
        String[] variables=DatosEntrada.DatosContinuos.getSimboloVariable();
        
        String[] NameResticc=DatosEntrada.DatosContinuos.getRestriccionesName();
        
        int [] SignoRestricciones=DatosEntrada.DatosContinuos.getSimboloRestricciones();
        double[] ladoderecho=DatosEntrada.DatosContinuos.getLadosDerechos();
        double[][] coeficienteRestricc=DatosEntrada.DatosContinuos.getMatrizCoefRest();
        
        double[] Newladoderecho= new double[n_restricciones];
        
        prob=new Problem(n_restricciones,n_variables);
        
        prob.getMetadata().put("lp.isMaximize", "true");
        
        for(int j=0;j<n_variables;j++){
            //asigna coef variables de la funcion objetivo
            if(j<n_variables-1)
                prob.newVariable(variables[j]).setObjectiveCoefficient(0);
            if(j==n_variables-1)
                prob.newVariable("Xn+1").setObjectiveCoefficient(-1);
        }
        int posit=0;
        for(int l=0;l<n_restricciones;l++){
            
            if(l<ladoderecho.length)
                Newladoderecho[l]=ladoderecho[l];
            if(l>=ladoderecho.length){
                Newladoderecho[l]=ladoDre[posit];
                posit++;
            }
        }
        
        for(int k=0;k<n_restricciones;k++){
            byte signo=Constraint.FREE;
            
            if(k<ladoderecho.length){
                if(SignoRestricciones[k]==(-1))
                    signo= Constraint.LESS;
                if(SignoRestricciones[k]==(0))
                    signo= Constraint.EQUAL;
                if(SignoRestricciones[k]==1)
                    signo= Constraint.GREATER;
                
                prob.newConstraint(NameResticc[k]).setType(signo).setRightHandSide(Newladoderecho[k]);
            }else{
                prob.newConstraint("B["+k+"]").setType(Constraint.GREATER).setRightHandSide(Newladoderecho[k]);
            }
            
        }
        
        for(int j=0;j<n_variables;j++){
            for(int k=0;k<n_restricciones;k++){
                if(k<DatosEntrada.DatosContinuos.getNRestricciones()&&j!=n_variables-1)
                    prob.setCoefficientAt(NameResticc[k],variables[j],coeficienteRestricc[k][j]);
                if(k<DatosEntrada.DatosContinuos.getNRestricciones()&&j==n_variables-1)
                    prob.setCoefficientAt(NameResticc[k],"Xn+1",0);
                if(k>=DatosEntrada.DatosContinuos.getNRestricciones()&&j!=n_variables-1)
                    prob.setCoefficientAt("B["+k+"]",variables[j],NewcoeficienteRestricc[k-DatosEntrada.DatosContinuos.getNRestricciones()][j]);
                if(k>=DatosEntrada.DatosContinuos.getNRestricciones()&&j==n_variables-1)
                    prob.setCoefficientAt("B["+k+"]","Xn+1",1);
            }
        }
        lp=new DenseSimplex(prob);
        double ans = lp.solve();
        //double ans = lp.getObjectiveValue();
        Zoptimo=ans;
        vectorXPCInf=lp.getSolution().getArray();
    }
    
    
    
    public static double[] getVectorXoptimos(){
        return vectorX;
    }
    public static double getValorZoptimo(){
        return Zoptimo;
    }
    
    public static double[] getVectorXoptimosMeta(){
        return vectorXMeta;
    }
    public static double[] getVectorXoptimosPCInf(){
        return vectorXPCInf;
    }
    public static double getValorZoptimoMeta(){
        return ZoptimoMeta;
    }
    
    public static double[] calculoXporFtranspuesta(double[] vector, double[][] matriz)throws AlgebraException{
        double[] resp= new double[vector.length];
        AlgebraI algebra=new Algebra();
        
        VectorI X= new DenseVector(vector);
        MatrixI mat =new DenseMatrix(matriz);
        
        VectorI Respuesta= algebra.multiply(mat,X);
        resp=Respuesta.getArray();
        return resp;
    }
    
    //Procedimiento propio para el ecualizador
    
    public static double[] ProgramacionLinealEcual(int positObjMejorar, double[] posOtrosObj) throws DuplicateException, NotFoundException,InvalidException,NoSolutionException, UnboundedException, InfeasibleException, ConvergenceException, ScaleException {
        
        SizableProblemI prob;
        LinearProgrammingI lp = new DenseSimplex();
        
        int n_funciones=DatosEntrada.DatosContinuos.getNFunciones();
        int n_variables=DatosEntrada.DatosContinuos.getNVariables();
        int n_restricciones=DatosEntrada.DatosContinuos.getNRestricciones();
        double[][] matrizCoeficientes=DatosEntrada.DatosContinuos.getMatrizCoef();
        String[] variables=DatosEntrada.DatosContinuos.getSimboloVariable();
        String[] NameResticc=DatosEntrada.DatosContinuos.getRestriccionesName();
        String[] NameFunciones=DatosEntrada.DatosContinuos.getSimboloFuncion();
        int [] SignoRestricciones=DatosEntrada.DatosContinuos.getSimboloRestricciones();
        double[] ladoderecho=DatosEntrada.DatosContinuos.getLadosDerechos();
        double[][] coeficienteRestricc=DatosEntrada.DatosContinuos.getMatrizCoefRest();
        
        prob=new Problem(n_restricciones+n_funciones-1,n_variables);
        
        prob.getMetadata().put("lp.isMaximize", "true");
        
        
        
        //asigna coef de las variables de la funcion objetivo
        for(int j=0;j<n_variables;j++){
            prob.newVariable(variables[j]).setObjectiveCoefficient(matrizCoeficientes[positObjMejorar][j]);
            
        }
        
        // asigna las restricciones iniciales del problema
        for(int k=0;k<n_restricciones;k++){
            byte signo=Constraint.FREE;
            
            if(SignoRestricciones[k]==(-1))
                signo= Constraint.LESS;
            if(SignoRestricciones[k]==(0))
                signo= Constraint.EQUAL;
            if(SignoRestricciones[k]==1)
                signo= Constraint.GREATER;
            
            prob.newConstraint(NameResticc[k]).setType(signo).setRightHandSide(ladoderecho[k]);
        }
        
        // adicion de las nuevas restricciones y lado derecho
        
        for(int k=0;k<n_funciones;k++){
            if(k!=positObjMejorar){
                prob.newConstraint("Aux"+NameFunciones[k]).setType(Constraint.GREATER).setRightHandSide(posOtrosObj[k]);
                
            }
        }
        // asigna los coef de las restricciones iniciales
        for(int j=0;j<n_variables;j++){
            for(int k=0;k<n_restricciones;k++){
                prob.setCoefficientAt(NameResticc[k],variables[j],coeficienteRestricc[k][j]);
                
            }
        }
        
        // adicion los coeficientes de las nuevas restricciones
        for(int k=0;k<n_funciones;k++){
            if(k!=positObjMejorar){
                for(int l=0;l<n_variables;l++){
                    prob.setCoefficientAt(("Aux"+NameFunciones[k]),variables[l],matrizCoeficientes[k][l]);
                    
                }
            }
        }
        
        lp=new DenseSimplex(prob);
        double ans = lp.solve();
        //double ans = lp.getObjectiveValue();
        ZoptimoEcual=ans;
        vectorXEcual=lp.getSolution().getArray();
        
        return vectorXEcual;
    }
}